package pers.dawnyang.config.exception;

import java.util.Objects;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.validation.ValidationException;
import org.apache.shiro.authz.UnauthorizedException;
import org.springframework.validation.BindException;
import org.springframework.validation.BindingResult;
import org.springframework.validation.FieldError;
import org.springframework.web.bind.MethodArgumentNotValidException;
import org.springframework.web.bind.annotation.ControllerAdvice;
import org.springframework.web.bind.annotation.ExceptionHandler;
import org.springframework.web.bind.annotation.ResponseBody;
import lombok.extern.slf4j.Slf4j;
import pers.dawnyang.common.domain.Result;
import pers.dawnyang.common.enums.ResultEnum;
import pers.dawnyang.common.util.ResultUtil;

/**
 * 统一异常处理
 * 
 * @author dawn yang
 *
 */
@Slf4j
@ControllerAdvice
public class GlobalExceptionHandler {

  /**
   * 全局默认异常
   * 
   * @param request
   * @param e
   * @return
   */
  @ExceptionHandler(Exception.class)
  @ResponseBody
  public Result<String> defultExcepitonHandler(HttpServletRequest request, Exception e) {
    log.error("defultExcepiton:", e);
    return ResultUtil.globalError();
  }

  /**
   * 自定义业务异常，业务逻辑里面throw new BusinessException("错误信息！");
   * 
   * @param request
   * @param response
   * @param e
   * @return
   */
  @ExceptionHandler(BusinessException.class)
  @ResponseBody
  public Result<String> BusinessExcepitonHandler(HttpServletRequest request,
      HttpServletResponse response, BusinessException e) {
    log.error("BusinessException:", e);
    return ResultUtil.error(e.getCode(), e.getMsg());
  }

  /**
   * 参数校验异常
   * 
   * @param request
   * @param response
   * @param e
   * @return
   */
  @ExceptionHandler(MethodArgumentNotValidException.class)
  @ResponseBody
  public Result<String> MethodArgumentNotValidExceptionHandler(HttpServletRequest request,
      HttpServletResponse response, MethodArgumentNotValidException e) {
    log.error("MethodArgumentNotValidException:", e);
    BindingResult bindingResult = e.getBindingResult();
    StringBuilder errMsg = new StringBuilder(bindingResult.getFieldErrors().size() * 16);
    for (int i = 0; i < bindingResult.getFieldErrors().size(); i++) {
      if (i > 0) {
        errMsg.append(",");
      }
      FieldError error = bindingResult.getFieldErrors().get(i);
      errMsg.append(error.getField() + ":" + error.getDefaultMessage());
    }
    return ResultUtil.error(ResultEnum.VALIDE_ERROR.getCode(), errMsg.toString());
  }

  @ExceptionHandler(ValidationException.class)
  @ResponseBody
  public Result<String> ValidationExceptionHandler(HttpServletRequest request,
      HttpServletResponse response, ValidationException e) {
    log.error("ValidationException:", e);
    String message = e.getMessage();
    String str1 = message.substring(0, message.indexOf(":"));
    String str2 = message.substring(str1.length() + 1, message.length());
    return ResultUtil.error(ResultEnum.VALIDE_ERROR.getCode(), str2);
  }

  /** 拦截表单验证异常 */
  @ExceptionHandler(BindException.class)
  @ResponseBody
  public Result<String> bindException(BindException e) {
    log.error("BindException:", e);
    BindingResult bindingResult = e.getBindingResult();
    String msg = Objects.requireNonNull(bindingResult.getFieldError()).getDefaultMessage();
    return ResultUtil.error(ResultEnum.VALIDE_ERROR.getCode(), msg);
  }

  /**
   * 未授权异常，需要在进入controller之后才能捕获异常
   * 
   * @param request
   * @param response
   * @param e
   * @return
   */
  @ExceptionHandler(UnauthorizedException.class)
  @ResponseBody
  public Result<String> UnauthorizedExceptionHandler(HttpServletRequest request,
      HttpServletResponse response, UnauthorizedException e) {
    // log.error("UnauthorizedException:", e);
    return ResultUtil.error(ResultEnum.UNAUTH.getCode(), ResultEnum.UNAUTH.getMsg());
  }

}
